%% TCM модуляция

% Инициализация
clear all; % удаление всех переменных, функций и ссылок
clc;       % очистка командного окна

numFig = 0; % счетчик графиков

% Описание кода для 8-PSK
trel = struct('numInputSymbols', 4, 'numOutputSymbols', 8,...
    'numStates',       4, ...
    'nextStates', [0 0 1 1; 2 2 3 3; 0 0 1 1; 2 2 3 3],...
    'outputs',    [0 4 2 6; 1 5 3 7; 2 6 0 4; 3 7 1 5]);

% Модуляция без кодирования
qUncoding = trel.numInputSymbols;
mUncoding = log2(qUncoding);

E = 1; % энергия сигнала



k = 2; % число бит информации
m = log2(qUncoding);



%% Модуляция
[signalsUncoding, ~] = modulationSignals('PSK', qUncoding, E);

% сигнальное множество
numFig = numFig+1;
figure(numFig);
plot(signalsUncoding(1, :), signalsUncoding(2, :), 'k*');

for i = 1 : qUncoding
    text( signalsUncoding(1, i), signalsUncoding(2, i), [' ', num2str(i-1)], 'Color', 'b' );
end
title(['Signal set of uncoded systems, ', num2str(qUncoding), '-', 'PSK'])
xlabel('s_{i1}')
ylabel('s_{i2}')
axis('square');


%% TCM

SNRdBinit = 4;   % начальное значение отношения сигнал/шум
SNRdBfin  = 7;   % конечное значение отношения сигнал/шум
dSNRdB    = 0.5;   % шаг отношения сигнал/шум

nErrMax = 10000; % число ошибок, при котором завершается моделирование при
               % данном значении отношения сигнал/шум. Происходит переход
               % к следующему значению отношения сигнал/шум
               
listSNRdB = SNRdBinit : dSNRdB : SNRdBfin;

% практические вероятности ошибок при различном соотношении сигнал/шум
PeUncoding     = zeros( size(listSNRdB) );
Pe_bitUncoding = PeUncoding;


j = 1; % счетчик отношений сигнал к шуму
for SNRdB = listSNRdB
    
    % SNR = E/No
    % SNR - signal to noise ratio (отношение сигнал/шум)
    SNR = 10^(SNRdB/10); % перевод из децибел
    
    noise  = E/SNR;        % шум
    DNoise = noise/2;      % дисперсия шума, для БГШ D = NO/2
    sigma  = sqrt(DNoise); % среднее квадратичное отклонение
    
    l = 0; % счетчик испытаний
    
    % счетчики ошибок
    nBitErrUncoding = 0;
    nErrUncoding    = 0;
    
    while nBitErrUncoding < nErrMax
        % Случайные данные
        msg = randi([0 1], [k, 1]);
        
        % Генерация сигнала
        msgNum        = bi2de(msg', 'left-msb');
        pointUncoding = signalsUncoding(:, msgNum + 1);
        
        % Добавление шума
        noisePoint    = [sigma*randn; sigma*randn];
        pointUncoding = pointUncoding + noisePoint;
        
        % Прием
        [~, z] = min( pdist2(signalsUncoding', pointUncoding', 'euclidean') );
        z = z - 1; % переход от позиции сигнала к его номеру
        
        if ~isequal(msgNum, z)
            % сосчитать число битовых ошибок
            nBitErrUncoding = nBitErrUncoding + biterr(msgNum, z);
            nErrUncoding = nErrUncoding + 1;
            fprintf('SNRdB = %d/%d, l = %d, nBitErrUncoding = %d/%d\n',...
                    SNRdB, listSNRdB(end), l, nBitErrUncoding, nErrMax);
        end
        
        l = l+1; % перейти к следующему испытанию
    end
    
    % подсчитать вероятность ошибки в данном испытании
    Pe_bitUncoding(j) = nBitErrUncoding / (l * k);
    PeUncoding(j)     = nErrUncoding / l;
    
    fprintf('\nSNRdB = %d/%d, l = %d, nBitErrUncoding = %d/%d, Pe_bitUncoding(j) = %d\n\n',...
            SNRdB, listSNRdB(end), l, nBitErrUncoding, nErrMax, Pe_bitUncoding(j));
    
    j = j+1; % перейти к следующему соотношению отношения сигнала к шуму
end

%% Вывод графика зависимости вероятности ошибки от отношения сигнал/шум

% (E/N0)_bit = (E/N0) / m;
SNRdB_bitUncoding = listSNRdB / mUncoding;

listSNRdB_Th = listSNRdB;%= 4 : 0.1 : 20; % 
listSNRdB_bitUncoding_Th = listSNRdB_Th / mUncoding;

%% Теоретические значения
numFig = numFig+1;
figure(numFig);

SNR        = 10.^( listSNRdB / 10 );
listSNR_Th = 10.^( listSNRdB_Th / 10 );

thoerPeUncoding = 2 * Q(  sqrt( 2 * listSNR_Th ) * sin(pi/qUncoding)  );

semilogy(listSNRdB,   PeUncoding,      'k--*',...
         listSNRdB_Th,   thoerPeUncoding, 'k--')
title('Theoretic P_{e}')
xlabel('E/N_{o}, dB')
ylabel('P_{e}')
grid on

thoerPe_bitUncoding = thoerPeUncoding / m;

%% Практические значения
numFig = numFig+1;
figure(numFig);

% график зависимости вероятности ошибки от отношения сигнал/шум
% semilogy(SNRdB_bit, Pe_bit, 'k-o')
semilogy(SNRdB_bitUncoding, Pe_bitUncoding,      'k--*',...
         listSNRdB_bitUncoding_Th, thoerPe_bitUncoding, 'k--')
title('P_{e}')
xlabel('(E/N_{o})_{(bit)}, dB')
ylabel('P_{e}^{(bit)}')
grid on